#include "const/oPreDefine.h"
#include "platform/oBulletCache.h"
#include "platform/oBulletDef.h"
#include "platform/oTypes.h"
using namespace platform;
#include "const/oXml.h"
#include "model/oFace.h"
#define oCase case oBulletXml

oBulletCache::oBulletCache()
{
	_parser.setDelegator(this);
}

oBulletCache::~oBulletCache()
{
	oBulletCache::unload();
}

void oBulletCache::load( const char* filename )
{
	oBulletCache::unload();
	_parser.parse(filename);
}

void oBulletCache::unload()
{
	BOOST_FOREACH(oBulletDef* bulletDef, _bulletDefs)
	{
		bulletDef->release();
	}
	_bulletDefs.clear();
}

oBulletDef* oBulletCache::getBulletDef( uint32 index )
{
	if (index < _bulletDefs.size())
	{
		return _bulletDefs[index];
	}
	return nullptr;
}

oBulletCache& oBulletCache::sharedCache()
{
	static oBulletCache bulletCache;
	return bulletCache;
}

void oBulletCache::textHandler( void *ctx, const char *s, int len )
{ }

void oBulletCache::startElement( void *ctx, const char *name, const char **atts )
{
	switch (name[0])
	{
		oCase::Bullet:
			{
				float angle = 0;
				float speed = 0;
				bool isHighSpeed = false;
				float gravityFactor = 1.0f;
				for (int i = 0;atts[i] != nullptr;i++)
				{
					switch (atts[i][0])
					{
						oCase::Angle:
							angle = (float)atof(atts[++i]);
							break;
						oCase::Speed:
							speed = (float)atof(atts[++i]);
							break;
						oCase::IsHighSpeed:
							isHighSpeed = (atoi(atts[++i]) != 0);
							break;
						oCase::GravityFactor:
							gravityFactor = (float)atof(atts[++i]);
							break;
					}
				}
				_currentDef = oBulletDef::create();
				_currentDef->setVelocity(angle, speed);
				_currentDef->setIsHighSpeed(true);
				_currentDef->setGravityScale(gravityFactor);
			}
			break;
		oCase::Face:
			for (int i = 0;atts[i] != nullptr;i++)
			{
				const char* faceStr;
				CCPoint point;
				switch (atts[i][0])
				{
					case oFaceXml::Str:
						faceStr = atts[++i];
						break;
					case oFaceXml::Pos:
						oGetPosFromStr(atts[++i], point.x, point.y);
						break;
				}
				_faces.push(oFace::create(faceStr, point));
			}
			break;
	}
}

void oBulletCache::endElement( void *ctx, const char *name )
{
	switch (name[0])
	{
		oCase::Face:
			{
				oFace* face = _faces.top();
				_faces.pop();
				if (_faces.empty())
				{
					_currentDef->setFace(face);
				}
				else
				{
					oFace* parentFace = _faces.top();
					parentFace->addChild(face);
				}
			}
			break;
		oCase::Bullet:
			_currentDef->retain();
			_currentDef->type = _bulletDefs.size();
			_bulletDefs.push_back(_currentDef);
			break;
	}
}
